/* pgPoolLibP.h - page set object library private header file */

/* 
 * Copyright (c) 1995-2005 Wind River Systems, Inc. 
 *
 * The right to copy, distribute, modify or otherwise make use 
 * of this software may be licensed only pursuant to the terms 
 * of an applicable Wind River license agreement. 
 */ 

/*
modification history
--------------------
01i,03jun05,yvp  Added #ifndef	_ASMLANGUAGE. 
                 Updated copyright. #include now with angle-brackets.
01h,28sep04,tam  changed ADDR type to unsigned int
01g,13sep04,zl   error status code cleanup
01f,14may04,pcs  Rearrange values of PG_POOL_OPT_PHYS_XXX due to rearranging
                 of PAGE_MGR_ATTR_POOL_XXX values.
01e,03dec03,yp   adding NO_ACTION ERROR flag
01d,26nov03,zl   renamed avlLib to avlUintLib
01d,29nov03,yp   moving ADDR from vxTypesOld.h to here
01c,18nov03,yp   adding error code VM_NOT_INITIALIZED
01b,20oct03,zl   updated for new avlLib API
01a,08jul03,yp   merged from AE pgPoolLib.h and pgPoolLibP.h
*/

#ifndef __INCpgPoolLibPh
#define __INCpgPoolLibPh

#ifdef __cplusplus
extern "C" {
#endif

#include <dllLib.h>
#include <types/vxWind.h>
#include <private/semLibP.h>
#include <private/objLibP.h>
#include <avlUintLib.h>




/* defines */

#define	PG_POOL_SIZE_NODE_NB	16
#define	PG_POOL_ADDR_NODE_NB	16


/* status codes */

#define	S_pgPoolLib_WRONG_PAGE_SIZE		(M_pgPoolLib | 1)
#define	S_pgPoolLib_START_ADR_NOT_ALIGNED	(M_pgPoolLib | 2)
#define S_pgPoolLib_NOT_ENOUGH_FREE_PAGES	(M_pgPoolLib | 3)
#define S_pgPoolLib_WRONG_ALIGNMENT		(M_pgPoolLib | 4)
#define S_pgPoolLib_PAGE_RANGE_OUT_OF_POOL	(M_pgPoolLib | 5)
#define S_pgPoolLib_CANNOT_ADD_TO_POOL		(M_pgPoolLib | 6)
#define S_pgPoolLib_OPTION_UNCHANGEABLE		(M_pgPoolLib | 7)
#define S_pgPoolLib_PAGE_OVERLAP		(M_pgPoolLib | 8)
#define S_pgPoolLib_VM_NOT_INITIALIZED		(M_pgPoolLib | 9)
#define S_pgPoolLib_INVALID_POOL_TYPE		(M_pgPoolLib | 10)

#ifndef	_ASMLANGUAGE

/* typedefs */

typedef unsigned int  ADDR;

/*
 * the order of the fields in PAGE_POOL_ADDR_NODE and PAGE_POOL_SIZE_NODE
 * is important...
 */

typedef enum pg_pool_opt
    {
    PG_POOL_OPT_TYPE_MSK	= 0x0000000F,
    PG_POOL_OPT_TYPE_PHYS	= 0x00000001, /* physical address space       */
    PG_POOL_OPT_TYPE_VIRT	= 0x00000002, /* virtual address space	      */
    PG_POOL_OPT_TYPE_OTHER	= 0x00000004, /* undefined address space type */

    PG_POOL_OPT_ERROR_MSK	= 0x0000F000,
    PG_POOL_OPT_ERROR_SPD_FLAG	= 0x00001000, /* suspend task on alloc error  */
    PG_POOL_OPT_ERROR_LOG_FLAG	= 0x00002000, /* log error msg on alloc error */
    PG_POOL_OPT_ERROR_NONE_FLAG	= 0x00004000, /* do nothing on alloc error    */

    PG_POOL_OPT_PHYS_MSK	= 0x0F000000, /* type of physical page pool   */
    PG_POOL_OPT_PHYS_RAM	= 0x01000000, /* Real memory 		      */
    PG_POOL_OPT_PHYS_IO    	= 0x02000000, /* IO space 		      */
    PG_POOL_OPT_PHYS_ANY	= 0x0F000000, 

    PG_POOL_OPT_RESERVED_MSK	= 0xF0000000, /* reserved options fields      */
    PG_POOL_OPT_RESERVED_1	= 0x10000000, /* reserved options field 1     */
    PG_POOL_OPT_RESERVED_2	= 0x20000000, /* reserved options field 2     */
    PG_POOL_OPT_RESERVED_3	= 0x40000000, /* reserved options field 3     */
    PG_POOL_OPT_RESERVED_4	= 0x80000000, /* reserved options field 4     */

    PG_POOL_OPT_NONE		= 0x0
    } PG_POOL_OPT;

typedef struct
    {
    AVLU_NODE   avlAddr;	/* AVL tree sorted by the start addr key */ 
    void *      next;		/* next with same size */ 
    void *      prev;		/* prev with same size */ 
    ADDR        stopAddr;
    } PAGE_POOL_ADDR_NODE;

typedef struct
    {     
    AVLU_NODE   avlSize;	/* AVL tree sorted by the size key */ 
    void *      next;
    void *      prev;    
    } PAGE_POOL_SIZE_NODE;

typedef struct
    { 
    void *              next; 
    PAGE_POOL_ADDR_NODE node[16]; 
    } PAGE_POOL_ADDR_BLOCK; 
 
typedef struct
    { 
    void *              next; 
    PAGE_POOL_SIZE_NODE node[16]; 
    } PAGE_POOL_SIZE_BLOCK; 


/* 
 * Data structure for a pool section (i.e. piece of memory added to a
 * a page pool via pgPoolAddToPool) header.
 */

typedef struct page_pool_section_hdr
    {
    DL_NODE     sectionNode;		/* pointer to the next section */
    ADDR        startAddr;		/* start address  of this section */
    ADDR        endAddr;		/* last address  of this section */
    } PAGE_POOL_SECTION_HDR;

 
struct page_pool_obj /* PAGE_POOL_OBJ */
    {
    OBJ_CORE		objCore;
    ADDR		baseAddr;	/* start of pool */
    ADDR		endAddr;	/* last address of pool */
    UINT		pageSize;
    SEMAPHORE		sem;		/* page pool semaphore */
    UINT		numPages;	/* size of pool in pages XXXXXXXXX */
    UINT		numFreePages;	/* number of free pages in pool */
    UINT		minFreePages;	/* minimum number of free pages seen */
    PG_POOL_OPT		options;

    AVLU_TREE avlAddr;
    AVLU_TREE avlSize;

    PAGE_POOL_ADDR_NODE *  freeAddrNode;
    PAGE_POOL_SIZE_NODE *  freeSizeNode;
    PAGE_POOL_ADDR_BLOCK * freeAddrBlock;
    PAGE_POOL_SIZE_BLOCK * freeSizeBlock;

    DL_LIST  		sectionHdrLst; 	/* head of the link list  of  all    */
					/* memory sections added to the page */
					/* pool via pgPoolAddToPool()        */
    };
typedef enum pg_pool_page_state
    {
    PG_POOL_PG_STATE_MSK	= 0x0000000F,
    PG_POOL_PG_STATE_IN_RANGE	= 0x00000001, /* page is in pool adrs range */
    PG_POOL_PG_STATE_OUT_RANGE	= 0x00000002, /* page is out of adrs range */
    PG_POOL_PG_STATE_RESERVED	= 0x00000004, /* page is reserved */
    PG_POOL_PG_STATE_AVAILABLE	= 0x00000008, /* page is available */

    PG_POOL_PG_NONE		= 0x0
    } PG_POOL_PG_STATE;

/* page pool information/statistics structure */

typedef struct
    {
    UINT numPages,	   /* number of pages in the page pool	 	    */
         numFreePages,	   /* current number of free pages in the page pool */
         maxFreeBlockSize, /* number of page of the largest block of 	    */
	 		   /* contiguous free pages in the page pool 	    */
         minFreePages;	   /* minimum number of free page at any given time */
    UINT pageSize;	   /* size of a page in bytes			    */

    PG_POOL_OPT options;   /* options of the page pool			    */

    }  PAGE_POOL_INFO;


typedef struct page_pool_obj PAGE_POOL_OBJ;

/* function declarations */

extern PAGE_POOL_ID	pgPoolCreate (ADDR, UINT, UINT, PG_POOL_OPT);
extern STATUS		pgPoolAddToPool (PAGE_POOL_ID , ADDR, UINT);
extern STATUS		pgPoolDelete (PAGE_POOL_ID);
extern BOOL		pgPoolPageIsFree (PAGE_POOL_ID, ADDR, UINT);
extern BOOL		pgPoolPageIsAllocated (PAGE_POOL_ID, ADDR, UINT);
extern ADDR		pgPoolPageGet (PAGE_POOL_ID, UINT);
extern ADDR		pgPoolAlignedPageGet (PAGE_POOL_ID, UINT, UINT);
extern ADDR		pgPoolPageGetAt (PAGE_POOL_ID, ADDR, UINT);
extern STATUS		pgPoolPageRelease (PAGE_POOL_ID, ADDR, UINT);
extern BOOL		pgPoolPageRangeVerify (PAGE_POOL_ID , ADDR , UINT);
extern UINT		pgPoolPageSize (PAGE_POOL_ID);
extern STATUS		pgPoolOptionsSet (PAGE_POOL_ID, PG_POOL_OPT, 
					  PG_POOL_OPT);
extern STATUS		pgPoolOptionsGet (PAGE_POOL_ID, PG_POOL_OPT *);
extern STATUS		pgPoolInfoGet (PAGE_POOL_ID, PAGE_POOL_INFO *);

/* temporary place holder for these obj generic macros */

typedef unsigned int    OBJ_NEW_ID;

#define OBJ_INIT(pObj)                  objInit((OBJ_CORE *) pObj)
#define OBJ_CREATE(OBJ_TYPE)            objCreate (sizeof(OBJ_TYPE))
#define OBJ_DELETE(pObj)                objDelete((OBJ_CORE *) pObj)
#define OBJPTR_TO_ID(pObj)              (OBJ_NEW_ID) (pObj)
#define ID_TO_OBJPTR(objId)             (OBJ_CORE *) (objId)


/* object/id conversion definitions */

#define PP_OBJ_CREATE()         (PAGE_POOL_OBJ *) OBJ_CREATE (PAGE_POOL_OBJ)
#define PP_OBJ_DELETE(pObj)     OBJ_DELETE (pObj)
#define PP_OBJ_ID(pObj)         (PAGE_POOL_ID) OBJPTR_TO_ID (pObj)
#define PP_OBJ_PTR(objId)       (PAGE_POOL_OBJ *) ID_TO_OBJPTR (objId)
#define PP_OBJ_INIT(pObj)       OBJ_INIT(pObj)


/* function macros */

#define PG_POOL_OPT_CHECK_TYPE(opt, val) \
    (((opt) & (PG_POOL_OPT_TYPE_MSK)) == (val) ? TRUE : FALSE)
#define PG_POOL_OPT_CHECK_ERROR(opt, val) \
    (((opt) & (PG_POOL_OPT_ERROR_MSK)) == (val) ? TRUE : FALSE)
#define PG_POOL_OPT_CHECK_PHYS(opt,val) \
    (((opt) & (PG_POOL_OPT_PHYS_MSK)) == (val) ? TRUE : FALSE)
#define PG_POOL_OPT_TYPE_GET(opt)	((opt) & PG_POOL_OPT_TYPE_MSK)
#define PG_POOL_OPT_SET(opt, val)	((opt) |= (opt) | (val))

#define PG_POOL_PG_CHECK_STATE(state, val) \
	(((state) & (PG_POOL_PG_STATE_MSK)) == (val) ? TRUE : FALSE)
#define PG_POOL_PG_STATE_GET(state)		((state) & PG_POOL_PG_STATE_MSK)
#define PG_POOL_PG_STATE_SET(state, val)	((state) = (state) | (val))

#define	PAGE_POOL_VERIFY_ADDR_RANGE(poolId, pageAdr, numPages) \
		pgPoolPageRangeVerify(poolId, pageAdr, numPages)
#define	PAGE_POOL_VERIFY_ADDR(poolId, pageAdr) \
		pgPoolPageRangeVerify(poolId, pageAdr, 1)
#define	PAGE_POOL_VERIFY_ALLOC(poolId, pageAdr, numPages, action) \
		pgPoolPageStateVerify(poolId, pageAdr, numPages, \
				      PG_POOL_PG_STATE_RESERVED, action)
#define	PAGE_POOL_VERIFY_FREE(poolId, pageAdr, numPages, action) \
		pgPoolPageStateVerify(poolId, pageAdr, numPages, \
				      PG_POOL_PG_STATE_AVAILABLE, action)
#define	PAGE_POOL_VERIFY_PHYS_TYPE(poolId, attr) \
    		((PP_OBJ_PTR(poolId))->options & (attr & PG_POOL_OPT_PHYS_MSK))

/* defines for pgPoolPageStateVerify() */

#define PG_STATE_ACTION_NONE    0x0
#define PG_STATE_ACTION_CHANGE  0x1

#define PG_POOL_OPT_PUBLIC_MSK	(PG_POOL_OPT_TYPE_MSK | \
				 PG_POOL_OPT_ERROR_MSK | \
				 PG_POOL_OPT_PHYS_MSK)


/* variable declarations */

extern CLASS_ID pgPoolClassId;          /* memory partition class id */

/* non-published functions: can be used only by kernel components */

extern STATUS           pgPoolLibInit ();
extern PAGE_POOL_ID     pgPoolInit (PAGE_POOL_OBJ *, ADDR, UINT, UINT, 
				    PG_POOL_OPT);
extern BOOL             pgPoolPageStateVerify (PAGE_POOL_ID , ADDR, UINT,
                                               PG_POOL_PG_STATE, UINT);
extern STATUS		pgPoolShowInit();

#endif	/* _ASMLANGUAGE */

#ifdef __cplusplus
}
#endif

#endif /* __INCpgPoolLibPh */
